#include "VerifiedMessageBase.hpp"

//using namespace BFT;
using namespace BFT::messages; 

VerifiedMessageBase::VerifiedMessageBase()
{
	//dummy constructor, invoked only by some constructors of NextBatch (indirectly,
	// through MacArrayMessage() ) before calling the real constructor
}

VerifiedMessageBase::VerifiedMessageBase(uint16_t _tag, uint32_t _size, uint32_t _auth_size)
{
  /*
  fprintf(stderr,"Verified Message Base constructor\n");
  */	
  buffer_length = TAG_SIZE + SIZE_SIZE + _size + _auth_size; //tag + size + payload + authentication
  buffer.reset((char*)malloc(sizeof(char)*buffer_length), free);
  bzero(buffer.get(), buffer_length);
  
  info.tag =_tag;
  info.size = buffer_length; 
  info.payload_start =TAG_SIZE + SIZE_SIZE;
  info.payload_size = _size;
  info.authentication_start = info.payload_start + info.payload_size;
  info.authentication_size = _auth_size;
  
  *((int16_t*)((char*)buffer.get()))= htons(info.tag); // setting the tag
  //fprintf(stdout,"tag set\n");
  *((int32_t*)((char*)buffer.get()+ TAG_SIZE))= htonl(info.payload_size); // setting the size
  //fprintf(stdout,"size set\n");  
  /*
  printInfo();
  */
}

VerifiedMessageBase::VerifiedMessageBase(boost::shared_ptr<char> _buffer, int _buffer_length)
{
//  fprintf(stdout,"vmb constructor has been called. buffer_length:%d\n",_buffer_length);
  buffer_length = _buffer_length;
  buffer = _buffer;
  
  info.tag = ntohs(*((uint16_t*)(buffer.get())));
  info.size = buffer_length; //the total buffer length 
  info.payload_start = TAG_SIZE + SIZE_SIZE;
  info.payload_size =  ntohl(*((uint32_t*)(buffer.get() + TAG_SIZE)));
  info.authentication_start = info.payload_start + info.payload_size;
  info.authentication_size = info.size - info.payload_size - TAG_SIZE - SIZE_SIZE; //the message size - the payload size - (tag field + size field)  
  
}

/*
boost::shared_ptr<char> VerifiedMessageBase::buildNewBytes(int& _buffer_length)
{

	
	int new_buffer_length = TAG_SIZE + SIZE_SIZE + info.payload_size + info.authentication_size;
	fprintf(stdout,"generating new bytes, new_buffer_length=%d\n", new_buffer_length);
        boost::shared_ptr<char> new_bytes((char*)malloc( sizeof(char)*new_buffer_length ), free);

        bzero(new_bytes.get(), new_buffer_length);
        //fprintf(stdout,"zeroed\n");
        *((int16_t*)((char*)new_bytes.get()))= htons(info.tag); // setting the tag
        //fprintf(stdout,"tag set\n");
        *((int32_t*)((char*)new_bytes.get()+ TAG_SIZE))= htonl(info.payload_size); // setting the size
        //fprintf(stdout,"size set\n");
        memcpy((void*)((char*)new_bytes.get()+info.payload_start),(void*)((char*)buffer.get()+info.payload_start),info.payload_size); //setting the payload
        //fprintf(stdout,"payload set\n");
        memcpy((void*)((char*)new_bytes.get()+info.authentication_start),(void*)((char*)buffer.get()+info.authentication_start),info.authentication_size); //setting the authentication
        //fprintf(stdout,"authentication set\n");
        
        _buffer_length = new_buffer_length;
        
        return new_bytes;        
};
*/

boost::shared_ptr<char> VerifiedMessageBase::getBytes(int& _buffer_length)
{
	_buffer_length = buffer_length;
	return buffer;
}

boost::shared_ptr<char> VerifiedMessageBase::getBytes()
{
	return buffer;
}

bool VerifiedMessageBase::equals(boost::shared_ptr<VerifiedMessageBase> _other_vmb)
{
	if ((uint32_t)buffer_length != _other_vmb.get()->getTotalSize())
		return false;
		
	int other_length;	
	boost::shared_ptr<char> other_buffer=_other_vmb.get()->getBytes(other_length);
	bool different = false;
	for (int i=0; i<buffer_length;i++)
	{	
		different = different || ( (char*)buffer.get()[i] != (char*)other_buffer.get()[i] ) ;
	}
	return !different;
}

uint32_t VerifiedMessageBase::getPayloadSize() 
{
	return info.payload_size;
}

void VerifiedMessageBase::printInfo()
{
	fprintf(stdout,"VerifiedMessageBase information:\n");
	fprintf(stdout,"buffer length:...................:%d\n",buffer_length);
	fprintf(stdout,"message size:....................:%d\n",info.size);
	fprintf(stdout,"message tag:.....................:%d\n",info.tag);
	fprintf(stdout,"payload size.....................:%d\n",info.payload_size);
	fprintf(stdout,"payload start index..............:%d\n",info.payload_start);
	fprintf(stdout,"authentication size..............:%d\n",info.authentication_size);
	fprintf(stdout,"authentication start index.......:%d\n",info.authentication_start);
}

uint32_t VerifiedMessageBase::getTotalSize() 
{
  return info.size;
}
